

                ;	DTC LOADER
                ;
 0100 =         TBASE:	EQU	100H
 0100           	ORG	TBASE
 0000 =         BOOT:	EQU	0
 0005 =         BDOS:	EQU	5
 0006 =         MEMTOP:	EQU	BDOS+1	;TOP OF AVAILABLE MEMORY
                ;	BDOS FUNCTIONS
 0009 =         CONOUT:	EQU	9	;CONSOLE OUTPUT
 000A =         CONIN:	EQU	10	;CONSOLE INPUT
 000F =         OPENF:	EQU	15	;OPEN FILE
 0010 =         CLOSEF:	EQU	16	;CLOSE FILE
 0011 =         SEARCF: EQU	17	;SEARCH FIRST
 0014 =         READF:	EQU	20	;READ SECTOR
 0019 =         INTDSK:	EQU	25	;INTERROGATE DISK
                ;
 005C =         TFCB:	EQU	05CH	;DEFAULT FILE CONTROL BLOCK
 005C =         TET:	EQU	TFCB	;ENTRY TYPE
 005D =         TFN:	EQU	TET+1	;FILE NAME
 0065 =         TFT:	EQU	TFN+8	;FILE TYPE
 0068 =         TEX:	EQU	TFT+3	;FILE EXTENT
 006B =         TRC:	EQU	TEX+3	;RECORD COUNT
 006C =         TDM:	EQU	TRC+1	;DISK ALLOCATION MAP
 007C =         TNR:	EQU	TDM+16	;NEXT RECORD NUMBER
                ;
 0080 =         TBUFF:	EQU	080H	;DEFAULT BUFFER
                ;
 0080 =         SECSIZ:	EQU	128	;SECTOR SIZE
                ;
 000D =         CR:	EQU	0DH
 000A =         LF:	EQU	0AH
                ;
                ;
 0100 210000    LOAD:	LXI	H,0		;SAVE CP/M STACK POINTER
 0103 39        	DAD	SP
 0104 22DE01    	SHLD	SAVESP
 0107 31FC01    	LXI	SP,STACK	;SET STACK POINTER
 010A CDFC01    	CALL	INIT		;INITIALIZE FILE PARAMETERS
                ;
 010D 0E00      	MVI	C,0		;CLEAR BUFFER COUNT
 010F CD7C01    LOAD1:	CALL	GETCHR		;SCAN TO BEGIN OF LINE
 0112 FE3A      	CPI	':'
 0114 C20F01    	JNZ	LOAD1
 0117 11E001    	LXI	D,COUNT		;GET LOAD COUNT
 011A CDBA01    	CALL	HEXBYT
 011D 3AE001    	LDA	COUNT		;DONE?
 0120 B7        	ORA	A
 0121 CA8D01    	JZ	EXIT
 0124 11DA01    	LXI	D,LADDR		;GET LOAD ADDRESS
 0127 CDAE01    	CALL	GETADR
 012A E5        	PUSH	H		;ADD OFFSET
 012B 2ADA01    	LHLD	LADDR
 012E EB        	XCHG
 012F 2ADC01    	LHLD	OFFSET
 0132 19        	DAD	D
 0133 11FC01    	LXI	D,LOW		;IS ADDRESS IN LOADER?
 0136 CDD401    	CALL	COMPAR
 0139 EB        	XCHG
 013A F26601    	JP	LOAD2
 013D 114801    	LXI	D,ERMES		;YES
 0140 0E09      	MVI	C,CONOUT
 0142 CD0500    	CALL	BDOS
 0145 C38D01    	JMP	EXIT
 0148 4C4F414420ERMES:	DB	'LOAD ADDRESS WITHIN LOADER.',CR,LF,'$'
                ;
 0166 E1        LOAD2:	POP	H		;RESTORE BUFFER POINTER
 0167 CD7C01    	CALL	GETCHR		;SKIP SEPARATOR BYTE
 016A CD7C01    	CALL	GETCHR
 016D CDBA01    LOAD3:	CALL	HEXBYT		;LOAD DATA
 0170 E5        	PUSH	H
 0171 21E001    	LXI	H,COUNT		;DECREMENT COUNT
 0174 35        	DCR	M
 0175 E1        	POP	H
 0176 C26D01    	JNZ	LOAD3
 0179 C30F01    	JMP	LOAD1		;END OF LINE
                ;
                ;
                ;
                ;	GET CHARACTER FROM RECORD
                ;	IN - HL=BUFFER POINTER
                ;	      C=BUFFER COUNT
                ;	OUT-A=CHARACTER
                ;
 017C AF        GETCHR:	XRA	A	;BUFFER EMPTY?
 017D B9        	CMP	C
 017E C29F01    	JNZ	GETCH2
 0181 0E14      	MVI	C,READF	;YES. GET NEXT RECORD
 0183 C5        	PUSH	B
 0184 D5        	PUSH	D
 0185 CDA501    	CALL	FILEOP
 0188 D1        	POP	D
 0189 C1        	POP	B
 018A CA9A01    	JZ	GETCH1
 018D CDA301    EXIT:	CALL	CLOSE
 0190 0E00      	MVI	C,0	;RESTORE LOGGED DRIVE
 0191 =         DRIVE:	EQU	$-1
 0192 CD9201    	CALL	$
 0193 =         SELDSK:	EQU	$-2
 0195 2ADE01    	LHLD	SAVESP	;RESTORE CP/M STACK POINTER
 0198 F9        	SPHL
 0199 C9        	RET
                ;
 019A 218000    GETCH1:	LXI	H,TBUFF
 019D 0E80      	MVI	C,SECSIZ
 019F 7E        GETCH2:	MOV	A,M
 01A0 23        	INX	H
 01A1 0D        	DCR	C
 01A2 C9        	RET
                ;
                ;
                ;
                ;
 01A3 0E10      CLOSE:	MVI	C,CLOSEF
 01A5 115C00    FILEOP:	LXI	D,TFCB
 01A8 CD0500    	CALL	BDOS
 01AB FE00      	CPI	0
 01AD C9        	RET
                ;	GET ADDRESS
                ;	IN - HL=4 DIGIT ASCII HEX ADDRESS
                ;	     DE=ADDRESS OF RESULT
                ;
 01AE 13        GETADR:	INX	D	;POINT TO MOST SIGN. BYTE
 01AF CDBA01    	CALL	HEXBYT
 01B2 1B        	DCX	D
 01B3 1B        	DCX	D
 01B4 CDBA01    	CALL	HEXBYT
 01B7 13        	INX	D
 01B8 AF        	XRA	A
 01B9 C9        	RET
 01BA CDC901    HEXBYT:	CALL	ASCHEX
 01BD 07        	RLC
 01BE 07        	RLC
 01BF 07        	RLC
 01C0 07        	RLC
 01C1 47        	MOV	B,A
 01C2 CDC901    	CALL	ASCHEX
 01C5 80        	ADD	B
 01C6 12        	STAX	D
 01C7 13        	INX	D
 01C8 C9        	RET
 01C9 CD7C01    ASCHEX:	CALL	GETCHR
 01CC D630      	SUI	'0'
 01CE FE0A      	CPI	10
 01D0 F8        	RM
 01D1 D607      	SUI	7
 01D3 C9        	RET
                ;	COMPARE HL & DE
                ;	OUT - FLAGS ARE SET TO RESULT OF HL - DE
                ;
 01D4 7C        COMPAR:	MOV	A,H
 01D5 BA        	CMP	D
 01D6 C0        	RNZ
 01D7 7D        	MOV	A,L
 01D8 BB        	CMP	E
 01D9 C9        	RET
                ;
                ;
                ;	VARIABLES
 01DA 0000      LADDR:	DW	0	;LOAD ADDRESS
 01DC 0000      OFFSET:	DW	0	;LOAD OFFSET
 01DE 0000      SAVESP:	DW	0	;CP/M STACK POINTER
 01E0 0000      COUNT:	DW	0	;LOAD COUNT OF LINE
 01E2           	DS	26
                STACK:
 01FC =         LOW:	EQU	$	;LOW LOAD ADDRESS
                ;
                ;
 01FC 0E19      INIT:	MVI	C,INTDSK	;SAVE CURRENTLY LOGGED DISK
 01FE CD0500    	CALL	BDOS
 0201 329101    	STA	DRIVE
 0204 2A0100    	LHLD	BOOT+1		;GET SELECT DISK ADDRESS
 0207 2E1B      	MVI	L,3*9
 0209 229301    	SHLD	SELDSK
 020C 227602    	SHLD	INISEL
 020F 210000    	LXI	H,0		;CLEAR OFFSET
 0212 22DC01    	SHLD	OFFSET
 0215 0616      	MVI	B,22		;SET MAX CHAR SCAN
 0217 3A5D00    	LDA	TFN		;WAS FILE SPECIFIED?
 021A FE20      	CPI	' '
 021C C24002    	JNZ	INIT1
 021F 3E14      	MVI	A,20		;NO. SET MAX BUFFER LENGTH
 0221 328000    	STA	TBUFF
 0224 114303    INIT0:	LXI	D,FNMES		;OUTPUT FILENAME MESSAGE
 0227 0E09      	MVI	C,CONOUT
 0229 CD0500    	CALL	BDOS
 022C 118000    	LXI	D,TBUFF		;INPUT FILE NAME
 022F 0E0A      	MVI	C,CONIN
 0231 CD0500    	CALL	BDOS
 0234 CD3703    	CALL	CRLF
 0237 3A8100    	LDA	TBUFF+1		;# CHARS IN BUFFER
 023A FE00      	CPI	0
 023C CA2402    	JZ	INIT0
 023F 47        	MOV	B,A		;B:=# CHARS IN BUFFER
 0240 218100    INIT1:	LXI	H,TBUFF+1
 0243 3A8300    	LDA	TBUFF+3		;DRIVE SPECIFIED?
 0246 FE3A      	CPI	':'
 0248 C27C02    	JNZ	INITD3
 024B 23        	INX	H
 024C 7E        	MOV	A,M
 024D D641      	SUI	'A'		;YES. LEGAL DRIVE #
 024F FA5702    	JM	INITD1
 0252 FE10      	CPI	16
 0254 FA7302    	JM	INITD2
 0257 116202    INITD1:	LXI	D,DRVMES	;NO
 025A 0E09      	MVI	C,CONOUT
 025C CD0500    	CALL	BDOS
 025F C38D01    	JMP	EXIT
 0262 494E56414CDRVMES:	DB	'INVALID DRIVE.',CR,LF,'$'
 0273 C5        INITD2:	PUSH	B
 0274 4F        	MOV	C,A		;SELECT DRIVE
 0275 CD7502    	CALL	$
 0276 =         INISEL:	EQU	$-2
 0278 C1        	POP	B
 0279 218300    	LXI	H,TBUFF+3
                INITD3:
 027C 115C00    	LXI	D,TFCB
 027F 23        INIT2:	INX	H
 0280 13        	INX	D
 0281 7E        	MOV	A,M
 0282 FE2E      	CPI	'.'		;END OF NAME?
 0284 CAA002    	JZ	INIT4
 0287 FE20      	CPI	' '
 0289 CABF02    	JZ	INIT7
 028C FE0D      	CPI	CR
 028E CAD902    	JZ	INIT9
 0291 FE60      	CPI	060H		;NO. LOWER CASE?
 0293 DA9802    	JC	INIT3
 0296 D620      	SUI	020H		;YES. CONVERT TO UPPER CASE
 0298 12        INIT3:	STAX	D
 0299 05        	DCR	B
 029A C27F02    	JNZ	INIT2
 029D C3D902    	JMP	INIT9
 02A0 116400    INIT4:	LXI	D,TFT-1		;GET FILE TYPE
 02A3 23        INIT5:	INX	H
 02A4 13        	INX	D
 02A5 7E        	MOV	A,M
 02A6 FE20      	CPI	' '
 02A8 CABF02    	JZ	INIT7
 02AB FE0D      	CPI	CR
 02AD CAD902    	JZ	INIT9
 02B0 FE60      	CPI	060H
 02B2 DAB702    	JC	INIT6
 02B5 D620      	SUI	020H
 02B7 12        INIT6:	STAX	D
 02B8 05        	DCR	B
 02B9 C2A302    	JNZ	INIT5
 02BC F2D902    	JP	INIT9
 02BF 23        INIT7:	INX	H		;SCAN FOR OFFSET
 02C0 7E        	MOV	A,M
 02C1 FE3D      	CPI	'='
 02C3 CAD202    	JZ	INIT8
 02C6 FE0D      	CPI	CR
 02C8 CAD902    	JZ	INIT9
 02CB 05        	DCR	B
 02CC C2BF02    	JNZ	INIT7
 02CF C3D902    	JMP	INIT9
 02D2 23        INIT8:	INX	H		;GET OFFSET
 02D3 11DC01    	LXI	D,OFFSET
 02D6 CDAE01    	CALL	GETADR
                INIT9:
 02D9 3A6500    	LDA	TFT		;WAS FILE TYPE SPECIFIED?
 02DC FE20      	CPI	' '
 02DE C2F102    	JNZ	INIT11
 02E1 215103    	LXI	H,HEXMES	;SET FILE TYPE TO HEX
 02E4 116500    	LXI	D,TFT
 02E7 0603      	MVI	B,3
 02E9 7E        INIT10:	MOV	A,M
 02EA 12        	STAX	D
 02EB 23        	INX	H
 02EC 13        	INX	D
 02ED 05        	DCR	B
 02EE C2E902    	JNZ	INIT10
                INIT11:
 02F1 116800    	LXI	D,TEX		;CLEAR EXTENT AND
 02F4 0604      	MVI	B,4		; RECORD COUNT
 02F6 AF        	XRA	A
 02F7 12        INIT12:	STAX	D
 02F8 13        	INX	D
 02F9 05        	DCR	B
 02FA C2F702    	JNZ	INIT12
 02FD 117C00    	LXI	D,TNR		;CLEAR NEXT RECORD NUMBER
 0300 12        	STAX	D
 0301 0E11      	MVI	C,SEARCF
 0303 CDA501    	CALL	FILEOP		;LOOKUP HEX FILE
 0306 FEFF      	CPI	0FFH
 0308 C23103    	JNZ	INIT13
 030B 111603    	LXI	D,EXIMES	;OUTPUT ERROR MESSAGE
 030E 0E09      	MVI	C,CONOUT
 0310 CD0500    	CALL	BDOS
 0313 C38D01    	JMP	EXIT
 0316 4845582046EXIMES:	DB	'HEX FILE DOES NOT EXIST.',CR,LF,'$'
                INIT13:
 0331 0E0F      	MVI	C,OPENF		;OPEN HEX FILE
 0333 CDA501    	CALL	FILEOP
 0336 C9        	RET
                ;
                ;
 0337 114003    CRLF:	LXI	D,CRLFM
 033A 0E09      	MVI	C,CONOUT
 033C CD0500    	CALL	BDOS
 033F C9        	RET
 0340 0D0A24    CRLFM:	DB	 CR,LF,'$'
 0343 46494C454EFNMES:	DB	'FILENAME ... $'
 0351 484558    HEXMES:	DB	'HEX'
 0354           	END
